import Draw from 'ol/interaction/Draw'
import { unByKey } from 'ol/Observable.js'
import Overlay from 'ol/Overlay'
import { getArea, getLength } from 'ol/sphere.js'
import { Point, LineString, Polygon } from 'ol/geom.js'
import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style.js'
import { Vector as VectorLayer } from 'ol/layer'
import { Vector as VectorSource } from 'ol/source'
import RasterSource from 'ol/source/Raster'
var sketch
var helpTooltipElement
var helpTooltip
var measureTooltipElement
var measureTooltip
var continuePolygonMsg = ''
var continueLineMsg = ''
var draw
var layerIndex = 0
var toolLayer = {}
var sourceVector
var vectorLayer = null
var drawEndCallback

export default {
  measure(map, measureType, vm) {
    this.measure2(map, measureType, vm)
  },
  measure2(map, measureType, vm, cb) {
    drawEndCallback = cb
    /**
     * Handle pointer move.
     * @param {import("../src/ol/MapBrowserEvent").default} evt The event.
     */
    var pointerMoveHandler = (evt) => {
      if (evt.dragging) {
        return
      }
      /** @type {string} */

      var helpMsg = '点击开始测量'
      if (sketch) {
        var geom = sketch.getGeometry()
        if (geom instanceof Polygon) {
          helpMsg = continuePolygonMsg
        } else if (geom instanceof LineString) {
          helpMsg = continueLineMsg
        }
      }
      helpTooltipElement.innerHTML = helpMsg
      helpTooltip.setPosition(evt.coordinate)
      helpTooltipElement.classList.remove('hidden')
    }
    sourceVector = new VectorSource()
    vectorLayer = new VectorLayer({
      source: sourceVector,
      style: new Style({
        fill: new Fill({
          color: 'rgba(255, 255, 255, 0.2)' // 区域内颜色
        }),
        stroke: new Stroke({
          color: '#ffcc33',
          width: 2
        }),
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({
            color: '#ffcc33' // 边框颜色
          })
        })
      })
    })
    map.addLayer(vectorLayer)
    layerIndex++
    toolLayer[layerIndex] = {
      feature: null,
      measureTooltip: null
    }
    if (draw) {
      map.removeInteraction(draw)
    }
    // 添加map事件
    map.on('pointermove', (evt) => {
      draw ? pointerMoveHandler(evt) : map.removeOverlay(helpTooltip)
    })
    map.getViewport().addEventListener('mouseout', () => {
      helpTooltipElement && helpTooltipElement.classList.add('hidden')
    })
    // 绘制 点 线 面
    addInteraction()

    /**
     * Format length output.
     * @param {LineString} line The line.
     * @return {string} The formatted length.
     */
    var formatLength = (line) => {
      var sourceProj = map.getView().getProjection() // 获取投影坐标系
      var length = getLength(line, {
        projection: sourceProj
      })
      var output
      if (length > 100) {
        output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'
      } else {
        output = Math.round(length * 100) / 100 + ' ' + 'm'
      }
      return output
    }

    /**
     * Format area output.
     * @param {Polygon} polygon The polygon.
     * @return {string} Formatted area.
     */
    var formatArea = (polygon) => {
      var sourceProj = map.getView().getProjection() // 获取投影坐标系
      var area = getArea(polygon, {
        projection: sourceProj
      })
      var output
      if (area > 10000) {
        output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>'
      } else {
        output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'
      }
      return output
    }
    var formatArea2 = (polygon) => {
      var sourceProj = map.getView().getProjection() // 获取投影坐标系
      var area = getArea(polygon, {
        projection: sourceProj
      })
      var output = Math.round(area * 100) / 100
      return output
    }
    // 绘制 点 线 面
    function addInteraction() {
      draw = new Draw({
        source: sourceVector,
        type: measureType,
        style: new Style({
          fill: new Fill({
            color: 'rgba(255, 255, 255, 0.2)'
          }),
          stroke: new Stroke({
            color: 'rgba(0, 0, 0, 0.5)',
            lineDash: [10, 10],
            width: 2
          }),
          image: new CircleStyle({
            radius: 5,
            stroke: new Stroke({
              color: 'rgba(0, 0, 0, 0.7)'
            }),
            fill: new Fill({
              color: 'rgba(255, 255, 255, 0.2)'
            })
          })
        })
      })
      draw = new Draw({
        source: sourceVector,
        type: measureType
      })

      map.addInteraction(draw)
      createMeasureTooltip()
      createHelpTooltip()
      var listener
      draw.on('drawstart', (evt) => {
        sketch = evt.feature
        const type = sketch.getGeometry()
        if (type instanceof Point) {
          // 如果是绘制点
          const pointCoordinates = sketch.getGeometry().flatCoordinates
          const img = require('@/assets/images/map/position.png')
          measureTooltipElement.innerHTML = `<img style="width:20px;height:20px;margin:5px auto; display:block;" src="${img}" /><div>${pointCoordinates[0].toFixed(4)},${pointCoordinates[1].toFixed(4)}</div>`
          measureTooltip.setPosition(pointCoordinates)
          toolLayer[layerIndex].measureTooltip = measureTooltip
        } else {
          // 如果是绘制线和面
          var tooltipCoord = evt.coordinate
          listener = sketch.getGeometry().on('change', (evt) => {
            var geom = evt.target
            var output
            if (geom instanceof Polygon) {
              output = formatArea(geom)
              tooltipCoord = geom.getInteriorPoint().getCoordinates()
            } else if (geom instanceof LineString) {
              output = formatLength(geom)
              tooltipCoord = geom.getLastCoordinate()
            }
            const closeBtn = "<i class='tooltip-close-btn tooltip-close-btn_" + layerIndex + "' data-index='" + layerIndex + "'>×</i>"
            measureTooltipElement.innerHTML = output + closeBtn
            measureTooltip.setPosition(tooltipCoord)
            toolLayer[layerIndex].measureTooltip = measureTooltip
          })
        }
      })

      draw.on('drawend', (evt) => {
        toolLayer[layerIndex].feature = evt.feature
        measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'
        measureTooltip.setOffset([0, -7])
        sketch = null
        measureTooltipElement = null
        createMeasureTooltip()
        unByKey(listener)
        map.un('pointermove', pointerMoveHandler)
        map.removeInteraction(draw)
        if (drawEndCallback != null) {
          var geom = evt.feature.getGeometry()
          var output
          // 如果是绘制线和面
          var tooltipCoord = []
          if (geom instanceof Polygon) {
            output = formatArea2(geom)
            tooltipCoord = evt.feature.getGeometry().getCoordinates()
          }
          drawEndCallback(output, tooltipCoord)
        }
        draw = null
        // eslint-disable-next-line space-before-function-paren
        document.querySelector('.tooltip-close-btn_' + layerIndex).addEventListener('click', function () {
          vm.mapClickTrue = true
          vectorLayer.getSource().removeFeature(toolLayer[this.dataset.index].feature)
          map.removeOverlay(toolLayer[this.dataset.index].measureTooltip)
          delete toolLayer[this.dataset.index]
        })
      })
    }
    function createHelpTooltip() {
      if (helpTooltipElement) {
        helpTooltipElement.parentNode.removeChild(helpTooltipElement)
      }
      helpTooltipElement = document.createElement('div')
      helpTooltipElement.className = 'ol-tooltip hidden'
      helpTooltip = new Overlay({
        element: helpTooltipElement,
        offset: [15, 0],
        positioning: 'center-left'
      })
      map.addOverlay(helpTooltip)
    }
    function createMeasureTooltip() {
      if (measureTooltipElement) {
        measureTooltipElement.parentNode.removeChild(measureTooltipElement)
      }
      measureTooltipElement = document.createElement('div')
      measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'
      measureTooltip = new Overlay({
        element: measureTooltipElement,
        offset: [0, -15],
        positioning: 'bottom-center'
      })
      map.addOverlay(measureTooltip)
    }
  },
  // 清除测量
  clearMeasure(map) {
    for (const i in toolLayer) {
      vectorLayer.getSource().removeFeature(toolLayer[i].feature)
      map.removeOverlay(toolLayer[i].measureTooltip)
    }
    toolLayer = {}
    layerIndex = 0
  },
  reverseFunc(pixelsTemp) {
    // 蓝色
    for (var i = 0; i < pixelsTemp.length; i += 4) {
      var r = pixelsTemp[i]
      var g = pixelsTemp[i + 1]
      var b = pixelsTemp[i + 2]
      // 运用图像学公式，设置灰度值
      var grey = r * 0.3 + g * 0.59 + b * 0.11
      // 将rgb的值替换为灰度值
      pixelsTemp[i] = grey
      pixelsTemp[i + 1] = grey
      pixelsTemp[i + 2] = grey

      // 基于灰色，设置为蓝色，这几个数值是我自己试出来的，可以根据需求调整
      pixelsTemp[i] = 55 - pixelsTemp[i]
      pixelsTemp[i + 1] = 255 - pixelsTemp[i + 1]
      pixelsTemp[i + 2] = 305 - pixelsTemp[i + 2]
    }
  },
  getSource(layer, type) {
    let reverseFunc
    if (type === 'gray') {
      reverseFunc = (pixelsTemp) => {
        // 灰色
        for (var i = 0; i < pixelsTemp.length; i += 4) {
          var r = pixelsTemp[i]
          var g = pixelsTemp[i + 1]
          var b = pixelsTemp[i + 2]
          // 运用图像学公式，设置灰度值
          var grey = r * 0.3 + g * 0.59 + b * 0.11
          // 将rgb的值替换为灰度值
          pixelsTemp[i] = grey
          pixelsTemp[i + 1] = grey
          pixelsTemp[i + 2] = grey
        }
      }
    } else if (type === 'blue') {
      reverseFunc = (pixelsTemp) => {
        // 蓝色
        for (var i = 0; i < pixelsTemp.length; i += 4) {
          var r = pixelsTemp[i]
          var g = pixelsTemp[i + 1]
          var b = pixelsTemp[i + 2]
          // 运用图像学公式，设置灰度值
          var grey = r * 0.3 + g * 0.59 + b * 0.11
          // 将rgb的值替换为灰度值
          pixelsTemp[i] = grey
          pixelsTemp[i + 1] = grey
          pixelsTemp[i + 2] = grey

          pixelsTemp[i] = 55 - pixelsTemp[i]
          pixelsTemp[i + 1] = 255 - pixelsTemp[i + 1]
          pixelsTemp[i + 2] = 305 - pixelsTemp[i + 2]
        }
      }
    } else if (type === 'darkgreen') {
      reverseFunc = (pixelsTemp) => {
        // 蓝色
        for (var i = 0; i < pixelsTemp.length; i += 4) {
          var r = pixelsTemp[i]
          var g = pixelsTemp[i + 1]
          var b = pixelsTemp[i + 2]
          // 运用图像学公式，设置灰度值
          var grey = r * 0.3 + g * 0.59 + b * 0.11
          // 将rgb的值替换为灰度值
          pixelsTemp[i] = grey
          pixelsTemp[i + 1] = grey
          pixelsTemp[i + 2] = grey

          pixelsTemp[i] = 33 - pixelsTemp[i]
          pixelsTemp[i + 1] = 255 - pixelsTemp[i + 1]
          pixelsTemp[i + 2] = 255 - pixelsTemp[i + 2]
        }
      }
    } else if (type === 'black') {
      reverseFunc = (pixelsTemp) => {
        // 灰色
        for (var i = 0; i < pixelsTemp.length; i += 4) {
          var r = pixelsTemp[i]
          var g = pixelsTemp[i + 1]
          var b = pixelsTemp[i + 2]
          // 运用图像学公式，设置灰度值
          var grey = r * 0.3 + g * 0.59 + b * 0.11
          // 将rgb的值替换为灰度值
          pixelsTemp[i] = grey
          pixelsTemp[i + 1] = grey
          pixelsTemp[i + 2] = grey

          // 黑色，依赖上边的灰色
          pixelsTemp[i] = 255 - pixelsTemp[i]
          pixelsTemp[i + 1] = 255 - pixelsTemp[i + 1]
          pixelsTemp[i + 2] = 255 - pixelsTemp[i + 2]
        }
      }
    } else if (type === 'reversal') {
      reverseFunc = (pixelsTemp) => {
        // 反转色
        for (var i = 0; i < pixelsTemp.length; i += 4) {
          pixelsTemp[i] = 255 - pixelsTemp[i]
          pixelsTemp[i + 1] = 255 - pixelsTemp[i + 1]
          pixelsTemp[i + 2] = 255 - pixelsTemp[i + 2]
        }
      }
    }

    if (reverseFunc) {
      const raster = new RasterSource({
        sources: [
          layer
        ],
        operationType: 'image',
        operation: (pixels, data) => {
          reverseFunc(pixels[0].data)
          return pixels[0]
        },
        threads: 10,
        lib: {
          reverseFunc: reverseFunc
        }
      })
      // raster.refresh()
      return raster
    } else {
      return layer
    }
  }

}
